﻿/******************************************************************************/
#include "stdafx.h"
#include "Main.h"
/******************************************************************************/
Neighbor::Neighbor()
{
   frame_animated=0;
   stand=walk=run=fist_l=fist_r=NULL;
}
/******************************************************************************/
// OPERATIONS
/******************************************************************************/
void Neighbor::said(Str text)
{
   Chat.New(name+": \""+text+"\"");
   if(text.length()>40)text.clip(40)+="..";
   chat_message=S+"\""+text+"\"";
   chat_time   =Time.appTime()+3+text.length()*(2.0f/40);
}
/******************************************************************************/
// ANIMATE
/******************************************************************************/
void Neighbor::animate()
{
   if(frame_animated!=Time.frame())
   {
      frame_animated=Time.frame();

      Matrix matrix;
      matrix.orn().setRotateY(-angle());
      matrix.pos=pos();

      Flt idle_time=Time.time()      ,
          move_time=Time.time()*0.68f;

      // basic animations
      cskel.clear  ()
           .animate(fist_l, idle_time, 1)
           .animate(fist_r, idle_time, 1)
           .animate(stand , idle_time, (1-stop_move()))
           .animate(walk  , move_time, (  stop_move())*(1-walk_run()))
           .animate(run   , move_time, (  stop_move())*(  walk_run()));

      // custom animations
      FREPA(motions)cskel.animate(motions[i], true);

      // update matrixes
      cskel.updateMatrix(matrix).updateVelocities();

      // update inventory
      inv.update(cskel, NULL);
   }
}
/******************************************************************************/
// UPDATE
/******************************************************************************/
Bool Neighbor::update()
{
   // update interpolators
   time     .update();
   posi     .update(time);
   angle    .update(time);
   stop_move.update(time);
   walk_run .update(time);

   ctrl.actor.pos(pos());
   REPA(motions)if(!motions[i].updateAuto(3, 3))motions.remove(i, true);
   return true;
}
/******************************************************************************/
// DRAW
/******************************************************************************/
void Neighbor::draw2D()
{
   Vec2 screen; if(PosToScreen(pos()+Vec(0, cskel.scale()*0.75f, 0), screen))
   {
      TextStyle ts; ts.scale/=2; D.text(ts, screen, name);
      if(chat_message.is() && Time.appTime()<=chat_time)D.text(ts, screen-Vec2(0, ts.scale.y), chat_message);
   }
}
/******************************************************************************/
UInt Neighbor::drawPrepare()
{
   if(mesh)if(Frustum(Ball(cskel.scale(), pos())))
   {
      animate();
      inv  .drawPrepare(     );
      mesh->draw       (cskel);
   }
   return 0;
}
/******************************************************************************/
void Neighbor::drawShadow()
{
   if(mesh)if(Frustum(Ball(cskel.scale(), pos())))
   {
      animate();
      inv  .drawShadow(     );
      mesh->drawShadow(cskel);
   }
}
/******************************************************************************/
void Neighbor::drawBehind()
{
   if(mesh)if(Frustum(Ball(cskel.scale(), pos())))
   {
      animate();
      SetBehindBias(mesh->box.h()*cskel.scale());
      mesh->drawBehind(Color(64,128,255,255), Color(255,255,255,0), cskel);
   }
}
/******************************************************************************/
// NETWORK
/******************************************************************************/
void Neighbor::operator=(ChrInfo &ci)
{
   name=ci.name;
   mesh=ci.mesh;
   cskel.create(mesh ? mesh->skeleton() : NULL, ci.scale); 
   ctrl .create(Capsule(0.3f, ci.scale)).actor.kinematic(true).collision(false).obj(this);

   stand =&cskel.getSkelAnim("anim/stand.anim" );
   walk  =&cskel.getSkelAnim("anim/walk.anim"  );
   run   =&cskel.getSkelAnim("anim/run.anim"   );
   fist_l=&cskel.getSkelAnim("anim/fist-l.anim");
   fist_r=&cskel.getSkelAnim("anim/fist-r.anim");
}
/******************************************************************************/
void Neighbor::operator=(ChrVisuals &cv)
{
   inv.create(cv.inv);
}
/******************************************************************************/
void Neighbor::operator=(ChrPos &cp)
{
   time.update();
   posi     .step(cp.pos      , time);
   angle    .step(cp.angle    , time);
   stop_move.step(cp.stop_move, time);
   walk_run .step(cp.walk_run , time);
   if(time.first())
   {
      posi     .first();
      angle    .first();
      stop_move.first();
      walk_run .first();
   }
   time.step();
}
/******************************************************************************/
static Bool Create(Neighbor &neighbor, SockAddr &sa, Ptr user) {return true;}

Map<SockAddr, Neighbor> Neighbors(Create, Compare);
/******************************************************************************/
